﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace JamiexuBox
{

    [Serializable]
    struct _File
    {
        public Icon icon;

        public String name;

        public String path;
    };

    public partial class Form1 : Form
    {
        private List<_File> listItem1 = new List<_File>();
        private List<_File> listItem2 = new List<_File>();
        private List<_File> listItem3 = new List<_File>();
        private RegistryKey registryKey;

        private IntPtr nextClipboardViewer;


        [DllImport("User32.dll")]
        protected static extern int SetClipboardViewer(int hWndNewViewer);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);



        public Form1()
        {
            InitializeComponent();
            this.TopLevel = true;
            this.TopMost = true;
            this.ShowInTaskbar = false;
            this.listView1.LargeImageList = new ImageList();
            this.listView1.GridLines = true;
            this.listView2.GridLines = true;
            this.listView3.GridLines = true;
            this.registryKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\JamiexuBox");
            updatePosition();
            nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);
        }



        [StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public int iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };

        private void Form1_Load(object sender, EventArgs e)
        {
            setRunPath();
            loadConfigure();
            RefreshList(this.listView1);
            RefreshList(this.listView2);
            RefreshList(this.listView3);
            this.comboBox1.Items.AddRange(GoogleTranslate.getLanguages());
            this.comboBox1.SelectedIndex = 0;
        }


        private void updatePosition()
        {
            int x;
            int y;
            x = Convert.ToInt32(this.registryKey.GetValue("PositionX", -1));
            y = Convert.ToInt32(this.registryKey.GetValue("PositionY", -1));
            if (x == -1 || y == -1)
            {
                x = (SystemInformation.PrimaryMonitorSize.Width / 2) - (this.Width / 2);
                y = (SystemInformation.PrimaryMonitorSize.Height / 2) - (this.Height / 2);
            }
            this.Location = new Point(x, y);
        }

        private void setRunPath()
        {
            if (this.registryKey.GetValue("CurrentPath", null) == null)
            {
                this.registryKey.SetValue("CurrentPath", System.Environment.CurrentDirectory);
            }
        }

        private void Form1_Move(object sender, EventArgs e)
        {

            int rate = 20;
            int screenRight = Screen.PrimaryScreen.Bounds.Right;//屏幕右边缘
            int formRight = this.Left + this.Size.Width;//窗口右边缘=窗口左上角x+窗口宽度

            if (Math.Abs(screenRight - formRight) <= rate)//往右靠
                this.Location = new Point(screenRight - this.Size.Width, this.Top);//当前窗口坐标赋值，实现吸附

            if (Math.Abs(this.Left) <= rate)//往左靠
                this.Location = new Point(0, this.Top);

            int screenBottom = Screen.PrimaryScreen.Bounds.Bottom;//屏幕下边缘
            int formBottom = this.Top + this.Size.Height;//窗口下边缘
            if (Math.Abs(screenBottom - formBottom) <= rate)//往下靠
                this.Location = new Point(this.Left, screenBottom - this.Size.Height);

            if (Math.Abs(this.Top) <= rate)//往上靠
                this.Location = new Point(this.Left, 0);

            this.registryKey.SetValue("PositionX", this.Location.X);
            this.registryKey.SetValue("PositionY", this.Location.Y);
            //Console.WriteLine(this.Location.X + " " + this.Location.Y);

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (this.Top == 0)
            {
                if (Cursor.Position.X >= this.Location.X && Cursor.Position.Y >= this.Location.Y &&
                    Cursor.Position.X <= this.Location.X + this.Width &&
                        Cursor.Position.Y <= this.Location.Y + this.Height
                    )
                {
                    if (this.Height <= this.MaximumSize.Height)
                    {
                        if (this.FormBorderStyle != FormBorderStyle.FixedSingle)
                            this.FormBorderStyle = FormBorderStyle.FixedSingle;
                        this.Height += 100;
                    }


                }
                else if (this.Height > this.MinimumSize.Height)
                {
                    this.FormBorderStyle = FormBorderStyle.None;
                    this.Height -= 100;
                }
            }

            if (this.Top != 0)
            {
                if (this.Height <= this.MaximumSize.Height)
                {
                    if (this.FormBorderStyle != FormBorderStyle.FixedSingle)
                        this.FormBorderStyle = FormBorderStyle.FixedSingle;
                    this.Height += 100;
                }
            }

        }

        private void RefreshList(ListView list)
        {
            List<_File> _f = null;
            switch (list.Name)
            {
                case "listView1":
                    _f = listItem1;
                    break;
                case "listView2":
                    _f = listItem2;
                    break;
                case "listView3":
                    _f = listItem3;
                    break;
            }

            list.Items.Clear();
            list.BeginUpdate();
            foreach (var v in _f)
            {
                ListViewItem listViewItem = new ListViewItem();
                listViewItem.Font = new Font("微软雅黑", 10);
                if (v.icon != null)
                {
                    list.LargeImageList.Images.Add(v.name, v.icon);
                    listViewItem.ImageIndex = list.LargeImageList.Images.IndexOfKey(v.name);
                }
                listViewItem.Text = v.name;
                list.Items.Add(listViewItem);
            }
            list.EndUpdate();
        }

        private void listView_DragEnter(object sender, DragEventArgs e)
        {
            string name = (sender as ListView).Name;
            switch (name)
            {
                case "listView1":
                    if (e.Data.GetDataPresent(DataFormats.FileDrop))
                        e.Effect = DragDropEffects.Copy;
                    else
                        e.Effect = DragDropEffects.None;
                    break;
                case "listView2":
                    if (e.Data.GetDataPresent(DataFormats.FileDrop))
                        e.Effect = DragDropEffects.Copy;
                    else
                        e.Effect = DragDropEffects.None;
                    break;
                case "listView3":
                    if (e.Data.GetDataPresent(DataFormats.FileDrop))
                        e.Effect = DragDropEffects.Copy;
                    else
                        e.Effect = DragDropEffects.None;
                    break;
            }

        }

        private void listPut(int type, string path)
        {

            String name = Path.GetFileName(path).ToString();
            _File f;
            f.path = path;

            switch (type)
            {
                case 1:
                    if (!File.Exists(path))
                        return;
                    f.name = name.Replace(Path.GetExtension(path).ToString(), "");
                    f.icon = Icon.ExtractAssociatedIcon(path);
                    if (listItem1.IndexOf(f) == -1)
                        listItem1.Add(f);
                    break;
                case 2:
                    f.name = name;
                    f.icon = null;
                    if (listItem2.IndexOf(f) == -1 && Directory.Exists(path))
                        listItem2.Add(f);
                    break;
                case 3:
                    f.name = name;
                    f.icon = null;
                    if (listItem3.IndexOf(f) == -1 && File.Exists(path))
                        listItem3.Add(f);
                    break;
            }

        }

        private void listData(int type, String[] files)
        {
            foreach (var path in files)
            {
                listPut(type, path);
            }
        }


        private void listView_DragDrop(object sender, DragEventArgs e)
        {

            string name = (sender as ListView).Name;
            String[] files = e.Data.GetData(DataFormats.FileDrop, false) as String[];
            switch (name)
            {
                case "listView1":
                    listData(1, files);
                    break;
                case "listView2":
                    listData(2, files);
                    break;
                case "listView3":
                    listData(3, files);
                    break;
            }

            RefreshList(sender as ListView);
            string path = this.registryKey.GetValue("CurrentPath", null) + "";
            if (!path.Equals("null"))
                export(path);
            else
                export(System.Environment.CurrentDirectory);

        }

        private void loadConfigure()
        {
            string path = this.registryKey.GetValue("CurrentPath").ToString() + "\\jamiexu.software.dat";
            if (File.Exists(path))
            {
                FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                BinaryFormatter b = new BinaryFormatter();
                this.listItem1 = (List<_File>)b.Deserialize(fileStream);
                fileStream.Close();
            }

            path = this.registryKey.GetValue("CurrentPath").ToString() + "\\jamiexu.folder.dat";
            if (File.Exists(path))
            {
                FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                BinaryFormatter b = new BinaryFormatter();
                this.listItem2 = (List<_File>)b.Deserialize(fileStream);
                fileStream.Close();
            }

            path = this.registryKey.GetValue("CurrentPath").ToString() + "\\jamiexu.file.dat";
            if (File.Exists(path))
            {
                FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                BinaryFormatter b = new BinaryFormatter();
                this.listItem3 = (List<_File>)b.Deserialize(fileStream);
                fileStream.Close();
            }
        }

        private void listView_DoubleClick(object sender, EventArgs e)
        {
            _File f;
            switch ((sender as ListView).Name)
            {
                case "listView1":
                    if (this.listView1.SelectedItems.Count == 0)
                        return;
                    f = this.listItem1[this.listView1.Items.IndexOf(this.listView1.SelectedItems[0])];
                    try
                    {
                        Process.Start(f.path);
                    }
                    catch { }
                    break;


                case "listView2":
                    if (this.listView2.SelectedItems.Count == 0)
                        return;
                    f = this.listItem2[this.listView2.Items.IndexOf(this.listView2.SelectedItems[0])];
                    try
                    {
                        Process.Start(f.path);
                    }
                    catch { }
                    break;


                case "listView3":
                    if (this.listView3.SelectedItems.Count == 0)
                        return;
                    f = this.listItem3[this.listView3.Items.IndexOf(this.listView3.SelectedItems[0])];
                    try
                    {
                        Process.Start(f.path);
                    }
                    catch { }
                    break;
            }

        }


        private void export(string path)
        {
            FileStream fileStream = new FileStream(path + "\\jamiexu.software.dat", FileMode.Create);
            BinaryFormatter b = new BinaryFormatter();
            b.Serialize(fileStream, this.listItem1);
            fileStream.Close();


            fileStream = new FileStream(path + "\\jamiexu.folder.dat", FileMode.Create);
            b = new BinaryFormatter();
            b.Serialize(fileStream, this.listItem2);
            fileStream.Close();


            fileStream = new FileStream(path + "\\jamiexu.file.dat", FileMode.Create);
            b = new BinaryFormatter();
            b.Serialize(fileStream, this.listItem3);
            fileStream.Close();
        }
        private void exprotToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog save = new FolderBrowserDialog();
            //save.Filter = "(Dat数据文件)|*.dat";
            save.Description = "请选择导出的文件夹";
            if (save.ShowDialog() != DialogResult.OK)
                return;

            export(save.SelectedPath);
        }

        private void exportToolStripMenuItem_Click(object sender, EventArgs e)
        {
            export(this.registryKey.GetValue("CurrentPath", null) == null ?
                System.Environment.CurrentDirectory : this.registryKey.GetValue("CurrentPath", null) + "");
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
            Process.GetCurrentProcess().Kill();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Author: @Jamiexu\nBlog:blog.jamiexu.cn\nGitee:https://gitee.com/Jamie793/jamiexu-box", "About:");
        }

        private void onToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RegistryKey RKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
            RKey.SetValue("JamiexuBox", System.Windows.Forms.Application.ExecutablePath);
        }

        private void offToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RegistryKey RKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
            RKey.DeleteValue("JamiexuBox");
        }

        private void listView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Delete)
            {
                switch ((sender as ListView).Name)
                {
                    case "listView1":
                        for (int i = listView1.SelectedItems.Count - 1; i >= 0; i--)
                        {
                            listItem1.Remove(listItem1[listView1.Items.IndexOf(listView1.SelectedItems[i])]);
                        }
                        RefreshList(this.listView1);
                        break;
                    case "listView2":
                        for (int i = listView2.SelectedItems.Count - 1; i >= 0; i--)
                        {
                            listItem2.Remove(listItem2[listView2.Items.IndexOf(listView2.SelectedItems[i])]);
                        }
                        RefreshList(this.listView2);
                        break;
                    case "listView3":
                        for (int i = listView3.SelectedItems.Count - 1; i >= 0; i--)
                        {
                            listItem3.Remove(listItem3[listView3.Items.IndexOf(listView3.SelectedItems[i])]);
                        }
                        RefreshList(this.listView3);
                        break;
                }
                export(System.Environment.CurrentDirectory);
            }
        }

        private void updateRunPathToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.registryKey.SetValue("CurrentPath", System.Environment.CurrentDirectory);
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            this.richTextBox2.Text = GoogleTranslate.translateTo(this.richTextBox1.Text.Trim(), this.comboBox1.SelectedItem.ToString());
        }

        private void comboBox1_SelectedValueChanged(object sender, EventArgs e)
        {
            this.richTextBox2.Text = GoogleTranslate.translateTo(this.richTextBox1.Text.Trim(), this.comboBox1.SelectedItem.ToString());
        }


        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            // defined in winuser.h
            const int WM_DRAWCLIPBOARD = 0x308;
            const int WM_CHANGECBCHAIN = 0x030D;

            switch (m.Msg)
            {
                case WM_DRAWCLIPBOARD:
                    //OnClipboardChanged();
                    if (Convert.ToInt32(this.registryKey.GetValue("Clipboard", 0)) == 1)
                    {
                        string text = Clipboard.GetText();
                        if (text.Trim().Length == 0)
                            break;
                        this.richTextBox1.Text = text;
                        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    }
                    break;

                case WM_CHANGECBCHAIN:
                    if (m.WParam == nextClipboardViewer)
                        nextClipboardViewer = m.LParam;
                    else
                        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    break;

                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        private void yesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.registryKey.SetValue("Clipboard", 1);
        }

        private void noToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.registryKey.SetValue("Clipboard", 0);
        }
    }
}
